package alg;

import java.io.*;
import java.util.ArrayList;
import java.util.Random;

public class Main {
	
	public static void checkFiles() throws Exception
	{
		File f1 = new File("./check1.txt");
		File f2 = new File("./check2.txt");
		BufferedReader br1 = new BufferedReader(new InputStreamReader(new FileInputStream(f1)));
		BufferedReader br2 = new BufferedReader(new InputStreamReader(new FileInputStream(f2)));
		String s1 = "";
		String s2 = "";
		int i = 0;
		while((s1 = br1.readLine()) != null | (s2 = br2.readLine()) != null)
		{
			System.out.println("i="+i+" s1="+s1+" s2="+s2);
			if (s1 == null)
			{
				System.out.println("s1 null!");
				return;
			}
			else if (s2 == null)
			{
				System.out.println("s2 null!");
				return;
			}
			
			if (!s1.equals(s2))
			{
				System.out.println("s1 != s2!");
			}
		}
		
		System.out.println("done!");
	}
	
	protected static class Edge{
		public int i;
		public int j;
	}
	
	public static boolean correctnesstester()
	{
		Random r = new Random();
		ArrayList<Edge> list = new ArrayList<Edge>();
		int seed = r.nextInt();
		if (seed < 0)
			seed *= -1;
		System.out.println("seed="+seed);
		r = new Random(seed);
		int n = 60;
		Fw fw = new Fw(n);
		TrueDyn td = new TrueDyn(n);
		double pr = 0;
		int insertCount = 0;
		int deleteCount = 0;
		int maxCount = 10*n*n;
		for (int k = 0; k<maxCount; k++)
		{
			
			double insert = r.nextDouble();
			boolean isInsert = false;
			if (insert > pr)
			{
				insertCount++;
				isInsert = true;
				int i = r.nextInt(n);
				int j = r.nextInt(n);
				Edge e = new Edge();
				e.i = i;
				e.j = j;
				list.add(e);
				fw.insert(i, j);
				td.insert(i, j);
			}
			else if (list.size() > 0)
			{
				deleteCount++;
				int index = r.nextInt(list.size());
				//System.out.println("delete!");
				Edge e = list.get(index);
				list.remove(index);
				fw.delete(e.i, e.j);
				td.delete(e.i, e.j);
			}
			else
			{
				continue;
			}
			
			pr = ((float)list.size())/((float)(n*n));
			int fwcount = fw.countTrans();
			int tdcount = td.countTrans();
			//System.out.println("fwcount="+fwcount+" tdcount="+tdcount);
			//System.out.println("last operation was "+(isInsert ? "insert" : "delete"));
			if (fwcount != tdcount)
			{
				System.out.println("Error counts are wrong!");
				return false;
			}
		}
		
		System.out.println("deleteCount="+deleteCount+" insertCount="+insertCount);
		return true;
	}
	
	public static void correctness(String file) throws Exception
	{

		File f = new File(file);
		Fw fw = null;
		TrueDyn td = null;
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
		String s = "";
		while ((s = br.readLine()) != null)
		{
			if (s.startsWith("init"))
			{
				s = s.substring(5, s.length()-1);
				td = new TrueDyn(Integer.parseInt(s));
				fw = new Fw(Integer.parseInt(s));
			}
			else if (s.startsWith("transitive"))
			{
				int ff = fw.countTrans();
				int t = td.countTrans();
				//System.out.println(ff+" "+t);
				if (ff != t)
				{
					System.out.println("ff="+ff+" t="+t+" not equal!");
					System.exit(0);
				}
			}
			else if (s.startsWith("insert"))
			{
				s = s.substring(7, s.length()-1);
				String[] ints = s.split(",");
				int i = Integer.parseInt(ints[0]);
				int j = Integer.parseInt(ints[1]);
				fw.insert(i, j);
				td.insert(i, j);
				
			}
			else if (s.startsWith("delete"))
			{
				s = s.substring(7, s.length()-1);
				String[] ints = s.split(",");
				int i = Integer.parseInt(ints[0]);
				int j = Integer.parseInt(ints[1]);
				fw.delete(i, j);
				td.delete(i,j);
			}
		}

	}
	
	public static void performanceTest(String[] args) throws Exception
	{
		if (args.length != 2)
		{
			System.out.println("Argument Error: Too few arguments");
			return;
		}
		
		if (args[0].equals("td"))
		{
			interpretDYN(args[1]);
		}
		else if (args[0].equals("fw"))
		{
			interpretFW(args[1]);
		}
		else
		{
			System.out.println("Argument Error: Invalid argument");
			return;
		}
	}
	
	public static void main(String[] args) throws Exception
	{
		//performanceTest(args);
		
		int nn = 150;
		generator.TestGen.generate(nn, "toparse"+nn+".txt");
		//System.out.println(generator.TestGen.generate(50));
		
		//interpret("toparse100.txt");
		
		//correctness("toparse300.txt");
		
		/*
		for (int i=0; i<100; i++)
		{
			System.out.println("starting test");
			if (!correctnesstester())
			{
				System.out.println("Test failed");
			}
			System.out.println("Test complete");
		}
		*/
		//String s = "./toparse100.txt";
		//interpretDYN(s);
		
		//interpretFW(s);
		//checkFiles();
		//System.out.println(Math.exteuclid(9, 13));
		//int[] k = Math.exteuclid(3, 7);
		//for (int i=0; i<k.length; i++)
			//System.out.println(k[i]);
		
		/*
		Random r = new Random(1234);
		for (int i=0; i<9001; i++)
		{
			int p = 42499;
			int x = r.nextInt(p-1)+1;
			int k = Math.inv(x, p);
			int c = (k*x) % p;
			if (c != 1)
			{
				System.out.println("Error, k not inverse");
				System.out.println("x = "+x);
				System.out.println("p = "+p);
				System.out.println("k = "+k);
			}
		}
		*/
		/*
		TrueDyn td = new TrueDyn(2);
		
		td.insert(0, 1);
		System.out.println(td.countTrans());
		td.insert(1, 0);
		System.out.println(td.countTrans());
		td.delete(1, 0);
		System.out.println(td.countTrans());
		print(td);
		*/	
	}
	
	public static void print(TrueDyn td)
	{
		td.printIMB();
		System.out.println("---------------");
		td.printInverse();
		System.out.println("---------------");
		td.printDeterminant();
	}
	
	public static void interpretDYN(String file) throws Exception
	{
		File f = new File(file);
		TrueDyn fw = null;
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
		String s = "";
		//Random r = new Random();
		while ((s = br.readLine()) != null)
		{
			/*
			for (int i=0; i<30; i++)
			{
				for (int j=0; j<30; j++)
				{
					long p = 2147483647;
					long calc = (((1234154151l * 1231412343l)%p) * ((124128321l * 2132141222l)%p))%p;
					/*
					calc = Math.minmod(1923124233l, calc, p);
					long cc = calc;
					p = cc + 1;
					
				}
			}*/
			if (s.startsWith("init"))
			{
				s = s.substring(5, s.length()-1);
				fw = new TrueDyn(Integer.parseInt(s));
			}
			else if (s.startsWith("transitive"))
			{
				int k = fw.countTrans();
				//System.out.println(k);
			}
			else if (s.startsWith("insert"))
			{
				s = s.substring(7, s.length()-1);
				String[] ints = s.split(",");
				fw.insert(Integer.parseInt(ints[0]), Integer.parseInt(ints[1]));
			}
			else if (s.startsWith("delete"))
			{
				s = s.substring(7, s.length()-1);
				String[] ints = s.split(",");
				fw.delete(Integer.parseInt(ints[0]), Integer.parseInt(ints[1]));
			}
		}
	}
	
	public static void interpretFW(String file) throws Exception
	{
		File f = new File(file);
		Fw fw = null;
		BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(f)));
		String s = "";
		while ((s = br.readLine()) != null)
		{
			if (s.startsWith("init"))
			{
				s = s.substring(5, s.length()-1);
				fw = new Fw(Integer.parseInt(s));
			}
			else if (s.startsWith("transitive"))
			{
				int k = fw.countTrans();
				//System.out.println(k);
				
			}
			else if (s.startsWith("insert"))
			{
				s = s.substring(7, s.length()-1);
				String[] ints = s.split(",");
				fw.insert(Integer.parseInt(ints[0]), Integer.parseInt(ints[1]));
			}
			else if (s.startsWith("delete"))
			{
				s = s.substring(7, s.length()-1);
				String[] ints = s.split(",");
				fw.delete(Integer.parseInt(ints[0]), Integer.parseInt(ints[1]));
			}
		}
	}
}
